# coding: utf-8
# @Author: cyl
# @File: 07三大器.py
# @Time: 2024/07/21 09:05:23
import time
from functools import wraps

"""1 迭代器
可迭代的对象: 可以直接用在循环的数据类型, 如list,tuple,dict,set,str, 还有generator(生成器)

迭代器(Iterator): 1、定义: 生成器不但可以用在循环中, 还能用next()不断调用返回下一个值, 直到爆出StopIteration异常, 
2、可迭代对象和迭代器和区别: 迭代器和可迭代对象不是同个概念, 区别在于是否有next函数(可以用dir(object)来查看此对象的所有支持的函数)

可迭代对象与迭代器之间的转换: 使用iter()函数将可迭代对象转换成迭代器
"""
from collections import Iterable


print(isinstance([], Iterable))
print(isinstance((), Iterable))
print(isinstance({}, Iterable))
print(isinstance("abc", Iterable))
print(isinstance((x for x in range(10)), Iterable)) # 生成器也是可迭代对象
print(isinstance(10, Iterable)) # 数字不是可迭代对象

# for i in range(10000):
#     print(i)

# 等同于
list1 = iter([1,2,3,4,5,6,7,8,9])
print(list1.__next__())
print(list1.__next__())


# class也可以是一个可迭代对象, 实现迭代器功能
class Abc(object):
    def __init__(self) -> None:
        self.myList = [1, 2, 3, 4, 5, 6]
    
    def __iter__(self):
        return self.myList[0]
    
    def __next__(self):
        for my in self.myList:
            print(my)


abc: Abc = Abc()
print(abc)


"""生成器"""
# 生成器函数
def path():
    yield 1
    yield 10
    yield 100
    yield 1000
    yield 10000
    yield 100000


my_path = path()
print() # <generator object path at 0x7fb5f801d0b0>
print(my_path.__next__())
print(my_path.__next__())
print(my_path.__next__())
print(my_path.__next__())
print(my_path.__next__())

# 生成器表达式 [value for value in xxx]
lst = [i for i in range(10)]
tup_lst = (i for i in range(10))
# 生成一个可迭代的生成器对象, 获取的话会调用迭代器的__next__()方法: 可以节省内存
print(tup_lst)   # <generator object <genexpr> at 0x7f9ca8058200>
print(tup_lst.__next__())
print(tup_lst.__next__())


"""装饰器"""
# 一、闭包函数
def abc():
    def wrapper():
        print("your code")
        return wrapper
    return wrapper
# eg1: 类的每个方法执行中我都需要查看他的执行时间
# eg2: 真实场景 -> 有部分接口在master 和 dev是不同的, master上有些服务的接口是不需要调用的, dev测试环境就需要调用
# dev开发环境 test/qa/release测试环境(qa1 qa2 qa3...) uat预生产(模拟真实环境) master生产
f = abc()
print('是否为闭包函数函数: ', f.__closure__)   # 是否为闭包函数函数:  None

# 二、装饰器
"""
    装饰器 = 高阶函数 + 函数嵌套 + 闭包
        1. 本质就是函数, 修饰其他函数: 为其它函数添加附加功能, 解决其它函数重复使用的功能
        2. 原则
            不修改被修饰函数的原代码
            不修改被修饰函数的调用方式
        3. @wraps(view_func)的作用: 不改变使用装饰器原有函数的结构(如name, doc)
        4. 语法糖: @timer 相当于 test = timer(test)
"""
# 2.1 普通装饰器(不带参数的装饰器) -> 我希望每次调用方法的时候都去打印一次日志和方法的执行时间 /yuque/?xxxx
def timer(func):
    @wraps(func)
    # func == eating()
    # bill()实在执行func
    def bill(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)
        end_time = time.time()
        print('不带参数的装饰器运行时间: ', end_time - start_time)
        return res

    return bill


@timer   # eating = timer(eating)
def eating():
    print([i for i in range(100000)])


@timer
def speaking():
    print([i for i in range(100000)])


# eating()
# speaking()


# 2.2 带参数且包含返回值的装饰器
def say_method(t: any):
    def op_time(func):
        @wraps(func)
        def bill(*args, **kwargs):
            if len(t) <= 10:
                start_time = time.time()
                res = func(*args, **kwargs)
                end_time = time.time()
                print('带参数的装饰器执行时间: ', end_time - start_time)
                return res
        return bill
    return op_time

lt: list = [1, 2, 3, 4, 5, 6]

@say_method(lt)
def cal():
    res = 0
    for i in lt:
        res += i
    return res


_sum = cal()
print(_sum)

# 2.3 eg2说明
def environment(t):
    """t: 环境"""
    def op_time(func):
        @wraps(func)
        def bill(*args, **kwargs):
            if t == "dev":
                print("dev正在执行, master不执行")
                res = func(*args, **kwargs)
                return res
        return bill
    return op_time


@environment("dev")
def create_order():
    print("...")


create_order()
